library(tidyverse)
Registered S3 methods overwritten by 'dbplyr':
  method         from
  print.tbl_lazy     
  print.tbl_sql      
── Attaching packages ───────────────────────────────────────────────────────────────────────────────────── tidyverse 1.3.1 ──
✓ ggplot2 3.3.5     ✓ purrr   0.3.4
✓ tibble  3.1.3     ✓ dplyr   1.0.7
✓ tidyr   1.1.3     ✓ stringr 1.4.0
✓ readr   2.0.1     ✓ forcats 0.5.1
── Conflicts ──────────────────────────────────────────────────────────────────────────────────────── tidyverse_conflicts() ──
x dplyr::filter() masks stats::filter()
x dplyr::lag()    masks stats::lag()
library(janitor)

Attaching package: ‘janitor’

The following objects are masked from ‘package:stats’:

    chisq.test, fisher.test
library(readODS)
library(httr)
library(here)
here() starts at /Users/tomdavie/Documents/GitHub/ev_climate_change_project
library(data.table)
Registered S3 method overwritten by 'data.table':
  method           from
  print.data.table     
data.table 1.14.0 using 1 threads (see ?getDTthreads).  Latest news: r-datatable.com
**********
This installation of data.table has not detected OpenMP support. It should still work but in single-threaded mode.
This is a Mac. Please read https://mac.r-project.org/openmp/. Please engage with Apple and ask them for support. Check r-datatable.com for updates, and our Mac instructions here: https://github.com/Rdatatable/data.table/wiki/Installation. After several years of many reports of installation problems on Mac, it's time to gingerly point out that there have been no similar problems on Windows or Linux.
**********

Attaching package: ‘data.table’

The following objects are masked from ‘package:dplyr’:

    between, first, last

The following object is masked from ‘package:purrr’:

    transpose
library(sf)
Linking to GEOS 3.8.1, GDAL 3.2.1, PROJ 7.2.1
library(leaflet)
Registered S3 method overwritten by 'htmlwidgets':
  method           from         
  print.htmlwidget tools:rstudio
read_ods(here("raw_data/electric-vehicle-charging-device-statistics-june-2021.ods"))
Error in .parse_ods_file(file) : file does not exist
getwd()
APE <- read_ods("raw_data/APE_site_data_tables.ods", sheet = 2)
NO2 <- read_ods("raw_data/NO2_tables.ods")
registry <- GET("http://chargepoints.dft.gov.uk/api/retrieve/registry/format/csv/") %>% 
  content()
type <- GET("http://chargepoints.dft.gov.uk/api/retrieve/type/format/csv/") %>% 
  content()
read_csv("Documents/GitHub/ev_climate_change_project/raw_data/no2_by_grid_2019.csv")
air_pollution_cap <- GET("https://uk-air.defra.gov.uk/data/sos/service?service=AQD&request=GetCapabilities")
air_pollution_cap <- rbindlist(air_pollution$content, fill = TRUE)
air_pollution_cap <- unnest(air_pollution_cap)
air_pollution <- GET("https://uk-air.defra.gov.uk/data/sos/service?service=SOS&version=2.0.0&request=GetObserved&observedProperty=http://dd.eionet.europa.eu/vocabulary/aq/pollutant/8") %>% 
  content()
air_pollution$exceptions
air_pollution <- rbindlist(air_pollution, fill = TRUE) 
Error in rbindlist(air_pollution, fill = TRUE) : 
  Input is data.table but should be a plain list of items to be stacked
air_pollution <- unnest(air_pollution)

How many electric vehicles are on the road across the UK by LA?

# Reading in and skipping first 5 rows
uk_ev <- read_ods(here("raw_data/ev_by_la.ods"), sheet = 2, skip = 5)
# Making row 1 the variable name
names(uk_ev) <- uk_ev[1,] 
# Removing row 1 
uk_ev <- uk_ev[-1,] %>% 
  clean_names()
# loading in shape file 
uk_shape_file <- st_read(here("raw_data/Local_Authority_Districts__April_2019__UK_BFE_v2-shp/Local_Authority_Districts__April_2019__UK_BFE_v2.shp")) %>%
  clean_names() %>% 
  st_simplify(dTolerance = 1000) %>%
  st_transform("+proj=longlat +datum=WGS84") %>% 
  select(lad19cd, long, lat, geometry) 
Error in (function (cond)  : 
  error in evaluating the argument 'x' in selecting a method for function 'select': Cannot open "/Users/tomdavie/Documents/GitHub/ev_climate_change_project/raw_data/Local_Authority_Districts__April_2019__UK_BFE_v2-shp/Local_Authority_Districts__April_2019__UK_BFE_v2.shp"; The file doesn't seem to exist.
# Joining uk_ev + shape file 
uk_ev_map <- uk_ev %>% 
  left_join(uk_shape_file, by = c("ons_la_code_apr_2019" = "lad19cd")) %>% 
  drop_na() %>% 
  mutate(across(c(x2021_q1:x2011_q4), as.numeric)) %>% 
  st_as_sf()
    pal <- colorBin("Greens", domain = uk_ev_map$x2021_q1, bins = c(0, 500, 1000, 2500, 5000, 10000, 15000))
    
    uk_ev_map_labels <- sprintf(
      "<strong>%s</strong><br/>%g Electric Vehicles",
      uk_ev_map$region_local_authority_apr_2019_3, uk_ev_map$x2021_q1) %>% 
      lapply(htmltools::HTML)
# Geospatial of EV Vehicles in the UK 2021 Q1
uk_ev_map %>% 
  leaflet() %>% 
  setView(lng = -4.2026, lat = 55.8, zoom = 4.7, options = list()) %>%
  addProviderTiles(providers$CartoDB.Positron) %>% 
  addPolygons(fillColor = ~pal(x2021_q1),
    weight = 0.1,
    opacity = 0.9, 
    color = "black",
    fillOpacity = 0.8,
    highlightOptions = highlightOptions(color = "green", weight = 2,
                                        bringToFront = TRUE),
    label = uk_ev_map_labels,
    labelOptions = labelOptions(
      style = list("font-weight" = "normal", padding = "3px 8px"),
      textsize = "15px",
      direction = "auto")) %>% 
  addLegend(pal = pal, values = ~x2021_q1, opacity = 0.7, title = NULL,
            position = "bottomright")

How many electric vehicles are on the road across the UK by LA?

# Reading in and skipping first 5 rows
uk_ev_postcode <- read_ods(here("raw_data/ev_by_postcode.ods"), sheet = 2, skip = 6) %>% 
  rename("postcode" = PostcodeDistrict2)
Error: Can't rename columns that don't exist.
x Column `PostcodeDistrict2` doesn't exist.
Run `rlang::last_error()` to see where the error occurred.
# loading in shape file 
uk_shape_file_postcode <- st_read(here("raw_data/postcode_shape/EX_Sample.shp")) %>%
  clean_names() %>% 
  st_simplify(dTolerance = 1000) %>%
  st_transform("+proj=longlat +datum=WGS84") #%>% 
#  select(lad19cd, long, lat, geometry) 
# Joining uk_ev + shape file 
uk_ev_map_postcode <- uk_ev_postcode %>% 
  left_join(uk_shape_file_postcode, by = c("ons_la_code_apr_2019" = "lad19cd")) %>% 
  drop_na() %>% 
  mutate(across(c(x2021_q1:x2011_q4), as.numeric)) %>% 
  st_as_sf()
    pal <- colorBin("Greens", domain = uk_ev_map$x2021_q1, bins = c(0, 500, 1000, 2500, 5000, 10000, 15000))
    
    uk_ev_map_labels <- sprintf(
      "<strong>%s</strong><br/>%g Electric Vehicles",
      uk_ev_map$region_local_authority_apr_2019_3, uk_ev_map$x2021_q1) %>% 
      lapply(htmltools::HTML)
# Geospatial of EV Vehicles in the UK 2021 Q1
uk_ev_map %>% 
  leaflet() %>% 
  setView(lng = -4.2026, lat = 55.8, zoom = 4.7, options = list()) %>%
  addProviderTiles(providers$CartoDB.Positron) %>% 
  addPolygons(fillColor = ~pal(x2021_q1),
    weight = 0.1,
    opacity = 0.9, 
    color = "black",
    fillOpacity = 0.8,
    highlightOptions = highlightOptions(color = "green", weight = 2,
                                        bringToFront = TRUE),
    label = uk_ev_map_labels,
    labelOptions = labelOptions(
      style = list("font-weight" = "normal", padding = "3px 8px"),
      textsize = "15px",
      direction = "auto")) %>% 
  addLegend(pal = pal, values = ~x2021_q1, opacity = 0.7, title = NULL,
            position = "bottomright")
# Wrangling to create an EV count over time plot 
uk_ev_longer <- uk_ev %>%
  # Pivot longer to get year and count columns
  pivot_longer(cols = c(x2021_q1:x2011_q4), names_to = c("year"), values_to = "no_of_ev") %>% 
  # Filter so we only have UK as a whole data AND we only want final numbers of the year so Q4 
  filter(region_local_authority_apr_2019_3 == "United Kingdom" & str_detect(year, "q4")) %>% 
  # Simplify to just show year
  mutate(year = case_when(str_detect(year, "2021") ~ "2021",
         str_detect(year, "2020") ~ "2020",
         str_detect(year, "2019") ~ "2019",
         str_detect(year, "2018") ~ "2018",
         str_detect(year, "2017") ~ "2017",
         str_detect(year, "2016") ~ "2016",
         str_detect(year, "2015") ~ "2015",
         str_detect(year, "2014") ~ "2014",
         str_detect(year, "2013") ~ "2013",
         str_detect(year, "2012") ~ "2012",
         str_detect(year, "2011") ~ "2011"),
         year = as.numeric(year),
         no_of_ev = as.numeric(no_of_ev))

Row binding grid NO2 data

no2_2010 <- read_csv(here("raw_data/no2_by_grid_2010.csv"), skip = 6, 
  col_names = c("uk_grid_code", "x", "y", "no2"))
no2_2011 <- read_csv(here("raw_data/no2_by_grid_2011.csv"), skip = 6, 
  col_names = c("uk_grid_code", "x", "y", "no2"))
no2_2012 <- read_csv(here("raw_data/no2_by_grid_2012.csv"), skip = 6, 
  col_names = c("uk_grid_code", "x", "y", "no2"))
no2_2013 <- read_csv(here("raw_data/no2_by_grid_2013.csv"), skip = 6, 
  col_names = c("uk_grid_code", "x", "y", "no2"))
no2_2014 <- read_csv(here("raw_data/no2_by_grid_2014.csv"), skip = 6, 
  col_names = c("uk_grid_code", "x", "y", "no2"))
no2_2015 <- read_csv(here("raw_data/no2_by_grid_2015.csv"), skip = 6, 
  col_names = c("uk_grid_code", "x", "y", "no2"))
no2_2016 <- read_csv(here("raw_data/no2_by_grid_2016.csv"), skip = 6, 
  col_names = c("uk_grid_code", "x", "y", "no2"))
no2_2017 <- read_csv(here("raw_data/no2_by_grid_2017.csv"), skip = 6, 
  col_names = c("uk_grid_code", "x", "y", "no2"))
no2_2018 <- read_csv(here("raw_data/no2_by_grid_2018.csv"), skip = 6, 
  col_names = c("uk_grid_code", "x", "y", "no2"))
no2_2019 <- read_csv(here("raw_data/no2_by_grid_2019.csv"), skip = 6, 
  col_names = c("uk_grid_code", "x", "y", "no2"))

# Create empty data frame
no2_all <- data_frame()

# For each year, bind rows to one dataset
for (i in 2010:2019) {
  df_name <- paste0("no2_", i)
  df_input <- as.name(df_name)
  
  df <- eval(df_input) %>% 
    mutate(year = i)
  
no2_all <- bind_rows(no2_all, df)
  }
# Remove missing NO2 grid values
no2_clean <- no2_all %>% 
  filter(no2 != "MISSING")
library(proj4)
proj4string <- "+proj=tmerc +lat_0=49 +lon_0=-2 +k=0.9996012717 +x_0=400000 +y_0=-100000 +ellps=airy +datum=OSGB36 +units=m +no_defs"

no2_clean_row <- no2_clean %>% 
  rowid_to_column()

# Source data
xy <- no2_clean_row %>% 
  select(x, y, rowid)

# Transformed data
pj <- project(xy, proj4string, inverse=TRUE)
latlon <- data.frame(xy, lat=pj$y, lon=pj$x)
final <-  merge(no2_clean_row, latlon, by.x = "rowid", by.y = "rowid") %>%
  filter(year == 2019) %>% 
  select(lat, lon, no2) 
final %>% 
  head()
no2_annual_mean <- read_ods(here("raw_data/NO2_tables.ods"), sheet = 3, skip = 2) %>% 
  clean_names()
no2_annual_mean_all %>% 
  ggplot() +
  aes(x = year, y = annual_mean_no2concentration_mg_m3) + 
  geom_point() +
  geom_smooth(se = FALSE) +
  theme_minimal() +
  scale_y_continuous(breaks = seq(0, 70, 10), limits = c(0, 70)) +
  theme(axis.text.x = element_text(angle = 45, vjust = 0.5, hjust=1)) +
  labs(x = "\nYear\n", 
       y = "\nAnnual Mean NO2 Conc mg m3\n",
       title = "\nNO2 over time in the UK\n") 
`geom_smooth()` using method = 'loess' and formula 'y ~ x'

forecast_no2 <- no2_annual_mean_all %>% 
  dplyr::select(year, annual_mean_no2concentration_mg_m3) %>% 
  tsibble()
Error: Can't determine index and please specify argument `index`.
Run `rlang::last_error()` to see where the error occurred.
autoplot(forecast_no2)

LS0tCnRpdGxlOiAiUiBOb3RlYm9vayIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKYGBge3J9CmxpYnJhcnkodGlkeXZlcnNlKQpsaWJyYXJ5KGphbml0b3IpCmxpYnJhcnkocmVhZE9EUykKbGlicmFyeShodHRyKQpsaWJyYXJ5KGhlcmUpCmxpYnJhcnkoZGF0YS50YWJsZSkKbGlicmFyeShzZikKbGlicmFyeShsZWFmbGV0KQpsaWJyYXJ5KGxlYWZsZXQuZXh0cmFzKQpgYGAKCmBgYHtyfQpyZWFkX29kcyhoZXJlKCJyYXdfZGF0YS9lbGVjdHJpYy12ZWhpY2xlLWNoYXJnaW5nLWRldmljZS1zdGF0aXN0aWNzLWp1bmUtMjAyMS5vZHMiKSkKYGBgCgpgYGB7cn0KZ2V0d2QoKQpgYGAKCmBgYHtyfQpBUEUgPC0gcmVhZF9vZHMoInJhd19kYXRhL0FQRV9zaXRlX2RhdGFfdGFibGVzLm9kcyIsIHNoZWV0ID0gMikKYGBgCgpgYGB7cn0KTk8yIDwtIHJlYWRfb2RzKCJyYXdfZGF0YS9OTzJfdGFibGVzLm9kcyIpCmBgYAoKYGBge3J9CnJlZ2lzdHJ5IDwtIEdFVCgiaHR0cDovL2NoYXJnZXBvaW50cy5kZnQuZ292LnVrL2FwaS9yZXRyaWV2ZS9yZWdpc3RyeS9mb3JtYXQvY3N2LyIpICU+JSAKICBjb250ZW50KCkKYGBgCgpgYGB7cn0KdHlwZSA8LSBHRVQoImh0dHA6Ly9jaGFyZ2Vwb2ludHMuZGZ0Lmdvdi51ay9hcGkvcmV0cmlldmUvdHlwZS9mb3JtYXQvY3N2LyIpICU+JSAKICBjb250ZW50KCkKYGBgCgpgYGB7cn0KcmVhZF9jc3YoIkRvY3VtZW50cy9HaXRIdWIvZXZfY2xpbWF0ZV9jaGFuZ2VfcHJvamVjdC9yYXdfZGF0YS9ubzJfYnlfZ3JpZF8yMDE5LmNzdiIpCmBgYAoKCmBgYHtyfQphaXJfcG9sbHV0aW9uX2NhcCA8LSBHRVQoImh0dHBzOi8vdWstYWlyLmRlZnJhLmdvdi51ay9kYXRhL3Nvcy9zZXJ2aWNlP3NlcnZpY2U9QVFEJnJlcXVlc3Q9R2V0Q2FwYWJpbGl0aWVzIikKYGBgCgpgYGB7cn0KYWlyX3BvbGx1dGlvbl9jYXAgPC0gcmJpbmRsaXN0KGFpcl9wb2xsdXRpb24kY29udGVudCwgZmlsbCA9IFRSVUUpCmBgYAoKYGBge3J9CmFpcl9wb2xsdXRpb25fY2FwIDwtIHVubmVzdChhaXJfcG9sbHV0aW9uX2NhcCkKYGBgCgoKYGBge3J9CmFpcl9wb2xsdXRpb24gPC0gR0VUKCJodHRwczovL3VrLWFpci5kZWZyYS5nb3YudWsvZGF0YS9zb3Mvc2VydmljZT9zZXJ2aWNlPVNPUyZ2ZXJzaW9uPTIuMC4wJnJlcXVlc3Q9R2V0T2JzZXJ2ZWQmb2JzZXJ2ZWRQcm9wZXJ0eT1odHRwOi8vZGQuZWlvbmV0LmV1cm9wYS5ldS92b2NhYnVsYXJ5L2FxL3BvbGx1dGFudC84IikgJT4lIAogIGNvbnRlbnQoKQpgYGAKCmBgYHtyfQphaXJfcG9sbHV0aW9uJGV4Y2VwdGlvbnMKYGBgCgpgYGB7cn0KYWlyX3BvbGx1dGlvbiA8LSByYmluZGxpc3QoYWlyX3BvbGx1dGlvbiRleGNlcHRpb25zLCBmaWxsID0gVFJVRSkgCmBgYAoKYGBge3J9CmFpcl9wb2xsdXRpb24gPC0gdW5uZXN0KGFpcl9wb2xsdXRpb24pCmBgYCAgIAoKIyBIb3cgbWFueSBlbGVjdHJpYyB2ZWhpY2xlcyBhcmUgb24gdGhlIHJvYWQgYWNyb3NzIHRoZSBVSyBieSBMQT8KCmBgYHtyfQojIFJlYWRpbmcgaW4gYW5kIHNraXBwaW5nIGZpcnN0IDUgcm93cwp1a19ldiA8LSByZWFkX29kcyhoZXJlKCJyYXdfZGF0YS9ldl9ieV9sYS5vZHMiKSwgc2hlZXQgPSAyLCBza2lwID0gNSkKIyBNYWtpbmcgcm93IDEgdGhlIHZhcmlhYmxlIG5hbWUKbmFtZXModWtfZXYpIDwtIHVrX2V2WzEsXSAKIyBSZW1vdmluZyByb3cgMSAKdWtfZXYgPC0gdWtfZXZbLTEsXSAlPiUgCiAgY2xlYW5fbmFtZXMoKQpgYGAKCmBgYHtyfQojIGxvYWRpbmcgaW4gc2hhcGUgZmlsZSAKdWtfc2hhcGVfZmlsZSA8LSBzdF9yZWFkKGhlcmUoInJhd19kYXRhL0xvY2FsX0F1dGhvcml0eV9EaXN0cmljdHNfX0FwcmlsXzIwMTlfX1VLX0JGRV92Mi1zaHAvTG9jYWxfQXV0aG9yaXR5X0Rpc3RyaWN0c19fQXByaWxfMjAxOV9fVUtfQkZFX3YyLnNocCIpKSAlPiUKICBjbGVhbl9uYW1lcygpICU+JSAKICBzdF9zaW1wbGlmeShkVG9sZXJhbmNlID0gMTAwMCkgJT4lCiAgc3RfdHJhbnNmb3JtKCIrcHJvaj1sb25nbGF0ICtkYXR1bT1XR1M4NCIpICU+JSAKICBzZWxlY3QobGFkMTljZCwgbG9uZywgbGF0LCBnZW9tZXRyeSkgCmBgYAoKYGBge3J9CiMgSm9pbmluZyB1a19ldiArIHNoYXBlIGZpbGUgCnVrX2V2X21hcCA8LSB1a19ldiAlPiUgCiAgbGVmdF9qb2luKHVrX3NoYXBlX2ZpbGUsIGJ5ID0gYygib25zX2xhX2NvZGVfYXByXzIwMTkiID0gImxhZDE5Y2QiKSkgJT4lIAogIGRyb3BfbmEoKSAlPiUgCiAgbXV0YXRlKGFjcm9zcyhjKHgyMDIxX3ExOngyMDExX3E0KSwgYXMubnVtZXJpYykpICU+JSAKICBzdF9hc19zZigpCmBgYAoKCmBgYHtyfQogICAgcGFsIDwtIGNvbG9yQmluKCJHcmVlbnMiLCBkb21haW4gPSB1a19ldl9tYXAkeDIwMjFfcTEsIGJpbnMgPSBjKDAsIDUwMCwgMTAwMCwgMjUwMCwgNTAwMCwgMTAwMDAsIDE1MDAwKSkKICAgIAogICAgdWtfZXZfbWFwX2xhYmVscyA8LSBzcHJpbnRmKAogICAgICAiPHN0cm9uZz4lczwvc3Ryb25nPjxici8+JWcgRWxlY3RyaWMgVmVoaWNsZXMiLAogICAgICB1a19ldl9tYXAkcmVnaW9uX2xvY2FsX2F1dGhvcml0eV9hcHJfMjAxOV8zLCB1a19ldl9tYXAkeDIwMjFfcTEpICU+JSAKICAgICAgbGFwcGx5KGh0bWx0b29sczo6SFRNTCkKYGBgCgpgYGB7cn0KIyBHZW9zcGF0aWFsIG9mIEVWIFZlaGljbGVzIGluIHRoZSBVSyAyMDIxIFExCnVrX2V2X21hcCAlPiUgCiAgbGVhZmxldCgpICU+JSAKICBzZXRWaWV3KGxuZyA9IC00LjIwMjYsIGxhdCA9IDU1LjgsIHpvb20gPSA0LjcsIG9wdGlvbnMgPSBsaXN0KCkpICU+JQogIGFkZFByb3ZpZGVyVGlsZXMocHJvdmlkZXJzJENhcnRvREIuUG9zaXRyb24pICU+JSAKICBhZGRQb2x5Z29ucyhmaWxsQ29sb3IgPSB+cGFsKHgyMDIxX3ExKSwKICAgIHdlaWdodCA9IDAuMSwKICAgIG9wYWNpdHkgPSAwLjksIAogICAgY29sb3IgPSAiYmxhY2siLAogICAgZmlsbE9wYWNpdHkgPSAwLjgsCiAgICBoaWdobGlnaHRPcHRpb25zID0gaGlnaGxpZ2h0T3B0aW9ucyhjb2xvciA9ICJncmVlbiIsIHdlaWdodCA9IDIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmluZ1RvRnJvbnQgPSBUUlVFKSwKICAgIGxhYmVsID0gdWtfZXZfbWFwX2xhYmVscywKICAgIGxhYmVsT3B0aW9ucyA9IGxhYmVsT3B0aW9ucygKICAgICAgc3R5bGUgPSBsaXN0KCJmb250LXdlaWdodCIgPSAibm9ybWFsIiwgcGFkZGluZyA9ICIzcHggOHB4IiksCiAgICAgIHRleHRzaXplID0gIjE1cHgiLAogICAgICBkaXJlY3Rpb24gPSAiYXV0byIpKSAlPiUgCiAgYWRkTGVnZW5kKHBhbCA9IHBhbCwgdmFsdWVzID0gfngyMDIxX3ExLCBvcGFjaXR5ID0gMC43LCB0aXRsZSA9IE5VTEwsCiAgICAgICAgICAgIHBvc2l0aW9uID0gImJvdHRvbXJpZ2h0IikKYGBgCiMgSG93IG1hbnkgZWxlY3RyaWMgdmVoaWNsZXMgYXJlIG9uIHRoZSByb2FkIGFjcm9zcyB0aGUgVUsgYnkgTEE/CgpgYGB7cn0KIyBSZWFkaW5nIGluIGFuZCBza2lwcGluZyBmaXJzdCA1IHJvd3MKdWtfZXZfcG9zdGNvZGUgPC0gcmVhZF9vZHMoaGVyZSgicmF3X2RhdGEvZXZfYnlfcG9zdGNvZGUub2RzIiksIHNoZWV0ID0gMiwgc2tpcCA9IDYpICU+JSAKICByZW5hbWUoInBvc3Rjb2RlIiA9ICJQb3N0Y29kZSBEaXN0cmljdDIiKQpgYGAKCmBgYHtyfQojIGxvYWRpbmcgaW4gc2hhcGUgZmlsZSAKdWtfc2hhcGVfZmlsZV9wb3N0Y29kZSA8LSBzdF9yZWFkKGhlcmUoInJhd19kYXRhL3Bvc3Rjb2RlX3NoYXBlL0VYX1NhbXBsZS5zaHAiKSkgJT4lCiAgY2xlYW5fbmFtZXMoKSAlPiUgCiAgc3Rfc2ltcGxpZnkoZFRvbGVyYW5jZSA9IDEwMDApICU+JQogIHN0X3RyYW5zZm9ybSgiK3Byb2o9bG9uZ2xhdCArZGF0dW09V0dTODQiKSAjJT4lIAojICBzZWxlY3QobGFkMTljZCwgbG9uZywgbGF0LCBnZW9tZXRyeSkgCmBgYAoKYGBge3J9CiMgSm9pbmluZyB1a19ldiArIHNoYXBlIGZpbGUgCnVrX2V2X21hcF9wb3N0Y29kZSA8LSB1a19ldl9wb3N0Y29kZSAlPiUgCiAgbGVmdF9qb2luKHVrX3NoYXBlX2ZpbGVfcG9zdGNvZGUsIGJ5ID0gYygib25zX2xhX2NvZGVfYXByXzIwMTkiID0gImxhZDE5Y2QiKSkgJT4lIAogIGRyb3BfbmEoKSAlPiUgCiAgbXV0YXRlKGFjcm9zcyhjKHgyMDIxX3ExOngyMDExX3E0KSwgYXMubnVtZXJpYykpICU+JSAKICBzdF9hc19zZigpCmBgYAoKCmBgYHtyfQogICAgcGFsIDwtIGNvbG9yQmluKCJHcmVlbnMiLCBkb21haW4gPSB1a19ldl9tYXAkeDIwMjFfcTEsIGJpbnMgPSBjKDAsIDUwMCwgMTAwMCwgMjUwMCwgNTAwMCwgMTAwMDAsIDE1MDAwKSkKICAgIAogICAgdWtfZXZfbWFwX2xhYmVscyA8LSBzcHJpbnRmKAogICAgICAiPHN0cm9uZz4lczwvc3Ryb25nPjxici8+JWcgRWxlY3RyaWMgVmVoaWNsZXMiLAogICAgICB1a19ldl9tYXAkcmVnaW9uX2xvY2FsX2F1dGhvcml0eV9hcHJfMjAxOV8zLCB1a19ldl9tYXAkeDIwMjFfcTEpICU+JSAKICAgICAgbGFwcGx5KGh0bWx0b29sczo6SFRNTCkKYGBgCgpgYGB7cn0KIyBHZW9zcGF0aWFsIG9mIEVWIFZlaGljbGVzIGluIHRoZSBVSyAyMDIxIFExCnVrX2V2X21hcCAlPiUgCiAgbGVhZmxldCgpICU+JSAKICBzZXRWaWV3KGxuZyA9IC00LjIwMjYsIGxhdCA9IDU1LjgsIHpvb20gPSA0LjcsIG9wdGlvbnMgPSBsaXN0KCkpICU+JQogIGFkZFByb3ZpZGVyVGlsZXMocHJvdmlkZXJzJENhcnRvREIuUG9zaXRyb24pICU+JSAKICBhZGRQb2x5Z29ucyhmaWxsQ29sb3IgPSB+cGFsKHgyMDIxX3ExKSwKICAgIHdlaWdodCA9IDAuMSwKICAgIG9wYWNpdHkgPSAwLjksIAogICAgY29sb3IgPSAiYmxhY2siLAogICAgZmlsbE9wYWNpdHkgPSAwLjgsCiAgICBoaWdobGlnaHRPcHRpb25zID0gaGlnaGxpZ2h0T3B0aW9ucyhjb2xvciA9ICJncmVlbiIsIHdlaWdodCA9IDIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmluZ1RvRnJvbnQgPSBUUlVFKSwKICAgIGxhYmVsID0gdWtfZXZfbWFwX2xhYmVscywKICAgIGxhYmVsT3B0aW9ucyA9IGxhYmVsT3B0aW9ucygKICAgICAgc3R5bGUgPSBsaXN0KCJmb250LXdlaWdodCIgPSAibm9ybWFsIiwgcGFkZGluZyA9ICIzcHggOHB4IiksCiAgICAgIHRleHRzaXplID0gIjE1cHgiLAogICAgICBkaXJlY3Rpb24gPSAiYXV0byIpKSAlPiUgCiAgYWRkTGVnZW5kKHBhbCA9IHBhbCwgdmFsdWVzID0gfngyMDIxX3ExLCBvcGFjaXR5ID0gMC43LCB0aXRsZSA9IE5VTEwsCiAgICAgICAgICAgIHBvc2l0aW9uID0gImJvdHRvbXJpZ2h0IikKYGBgCiAgCmBgYHtyfQojIFdyYW5nbGluZyB0byBjcmVhdGUgYW4gRVYgY291bnQgb3ZlciB0aW1lIHBsb3QgCnVrX2V2X2xvbmdlciA8LSB1a19ldiAlPiUKICAjIFBpdm90IGxvbmdlciB0byBnZXQgeWVhciBhbmQgY291bnQgY29sdW1ucwogIHBpdm90X2xvbmdlcihjb2xzID0gYyh4MjAyMV9xMTp4MjAxMV9xNCksIG5hbWVzX3RvID0gYygieWVhciIpLCB2YWx1ZXNfdG8gPSAibm9fb2ZfZXYiKSAlPiUgCiAgIyBGaWx0ZXIgc28gd2Ugb25seSBoYXZlIFVLIGFzIGEgd2hvbGUgZGF0YSBBTkQgd2Ugb25seSB3YW50IGZpbmFsIG51bWJlcnMgb2YgdGhlIHllYXIgc28gUTQgCiAgZmlsdGVyKHJlZ2lvbl9sb2NhbF9hdXRob3JpdHlfYXByXzIwMTlfMyA9PSAiVW5pdGVkIEtpbmdkb20iICYgc3RyX2RldGVjdCh5ZWFyLCAicTQiKSkgJT4lIAogICMgU2ltcGxpZnkgdG8ganVzdCBzaG93IHllYXIKICBtdXRhdGUoeWVhciA9IGNhc2Vfd2hlbihzdHJfZGV0ZWN0KHllYXIsICIyMDIxIikgfiAiMjAyMSIsCiAgICAgICAgIHN0cl9kZXRlY3QoeWVhciwgIjIwMjAiKSB+ICIyMDIwIiwKICAgICAgICAgc3RyX2RldGVjdCh5ZWFyLCAiMjAxOSIpIH4gIjIwMTkiLAogICAgICAgICBzdHJfZGV0ZWN0KHllYXIsICIyMDE4IikgfiAiMjAxOCIsCiAgICAgICAgIHN0cl9kZXRlY3QoeWVhciwgIjIwMTciKSB+ICIyMDE3IiwKICAgICAgICAgc3RyX2RldGVjdCh5ZWFyLCAiMjAxNiIpIH4gIjIwMTYiLAogICAgICAgICBzdHJfZGV0ZWN0KHllYXIsICIyMDE1IikgfiAiMjAxNSIsCiAgICAgICAgIHN0cl9kZXRlY3QoeWVhciwgIjIwMTQiKSB+ICIyMDE0IiwKICAgICAgICAgc3RyX2RldGVjdCh5ZWFyLCAiMjAxMyIpIH4gIjIwMTMiLAogICAgICAgICBzdHJfZGV0ZWN0KHllYXIsICIyMDEyIikgfiAiMjAxMiIsCiAgICAgICAgIHN0cl9kZXRlY3QoeWVhciwgIjIwMTEiKSB+ICIyMDExIiksCiAgICAgICAgIHllYXIgPSBhcy5udW1lcmljKHllYXIpLAogICAgICAgICBub19vZl9ldiA9IGFzLm51bWVyaWMobm9fb2ZfZXYpKQpgYGAKCgpgYGB7cn0KdWtfZXZfbG9uZ2VyICU+JSAKICBnZ3Bsb3QoKSArCiAgYWVzKHggPSB5ZWFyLCB5ID0gbm9fb2ZfZXYpICsKICBnZW9tX2NvbChmaWxsID0gImxhd25ncmVlbiIpICsKICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gYygyMDExOjIwMjApKSArCiAgc2NhbGVfeV9jb250aW51b3VzKGJyZWFrcyA9IHNlcSgwLCAyMjAwMDAsIGJ5ID0gMjAwMDApLCBsaW1pdHMgPSBjKDAsIDIyMDAwMCkpICsKICBsYWJzKHRpdGxlID0gIlxuTnVtYmVyIG9mIEVsZWN0cmljIFZlaGljbGVzIG92ZXIgdGltZSBpbiB0aGUgVUtcbiIsCiAgICAgICB4ID0gIlxuWWVhclxuIiwKICAgICAgIHkgPSAiXG5OdW1iZXIgb2YgRWxlY3RyaWMgVmVoaWNsZXNcbiIpICsKICB0aGVtZV9taW5pbWFsKCkgCmBgYAoKICAKCgojIFJvdyBiaW5kaW5nIGdyaWQgTk8yIGRhdGEgCgpgYGB7cn0Kbm8yXzIwMTAgPC0gcmVhZF9jc3YoaGVyZSgicmF3X2RhdGEvbm8yX2J5X2dyaWRfMjAxMC5jc3YiKSwgc2tpcCA9IDYsIAogIGNvbF9uYW1lcyA9IGMoInVrX2dyaWRfY29kZSIsICJ4IiwgInkiLCAibm8yIikpCm5vMl8yMDExIDwtIHJlYWRfY3N2KGhlcmUoInJhd19kYXRhL25vMl9ieV9ncmlkXzIwMTEuY3N2IiksIHNraXAgPSA2LCAKICBjb2xfbmFtZXMgPSBjKCJ1a19ncmlkX2NvZGUiLCAieCIsICJ5IiwgIm5vMiIpKQpubzJfMjAxMiA8LSByZWFkX2NzdihoZXJlKCJyYXdfZGF0YS9ubzJfYnlfZ3JpZF8yMDEyLmNzdiIpLCBza2lwID0gNiwgCiAgY29sX25hbWVzID0gYygidWtfZ3JpZF9jb2RlIiwgIngiLCAieSIsICJubzIiKSkKbm8yXzIwMTMgPC0gcmVhZF9jc3YoaGVyZSgicmF3X2RhdGEvbm8yX2J5X2dyaWRfMjAxMy5jc3YiKSwgc2tpcCA9IDYsIAogIGNvbF9uYW1lcyA9IGMoInVrX2dyaWRfY29kZSIsICJ4IiwgInkiLCAibm8yIikpCm5vMl8yMDE0IDwtIHJlYWRfY3N2KGhlcmUoInJhd19kYXRhL25vMl9ieV9ncmlkXzIwMTQuY3N2IiksIHNraXAgPSA2LCAKICBjb2xfbmFtZXMgPSBjKCJ1a19ncmlkX2NvZGUiLCAieCIsICJ5IiwgIm5vMiIpKQpubzJfMjAxNSA8LSByZWFkX2NzdihoZXJlKCJyYXdfZGF0YS9ubzJfYnlfZ3JpZF8yMDE1LmNzdiIpLCBza2lwID0gNiwgCiAgY29sX25hbWVzID0gYygidWtfZ3JpZF9jb2RlIiwgIngiLCAieSIsICJubzIiKSkKbm8yXzIwMTYgPC0gcmVhZF9jc3YoaGVyZSgicmF3X2RhdGEvbm8yX2J5X2dyaWRfMjAxNi5jc3YiKSwgc2tpcCA9IDYsIAogIGNvbF9uYW1lcyA9IGMoInVrX2dyaWRfY29kZSIsICJ4IiwgInkiLCAibm8yIikpCm5vMl8yMDE3IDwtIHJlYWRfY3N2KGhlcmUoInJhd19kYXRhL25vMl9ieV9ncmlkXzIwMTcuY3N2IiksIHNraXAgPSA2LCAKICBjb2xfbmFtZXMgPSBjKCJ1a19ncmlkX2NvZGUiLCAieCIsICJ5IiwgIm5vMiIpKQpubzJfMjAxOCA8LSByZWFkX2NzdihoZXJlKCJyYXdfZGF0YS9ubzJfYnlfZ3JpZF8yMDE4LmNzdiIpLCBza2lwID0gNiwgCiAgY29sX25hbWVzID0gYygidWtfZ3JpZF9jb2RlIiwgIngiLCAieSIsICJubzIiKSkKbm8yXzIwMTkgPC0gcmVhZF9jc3YoaGVyZSgicmF3X2RhdGEvbm8yX2J5X2dyaWRfMjAxOS5jc3YiKSwgc2tpcCA9IDYsIAogIGNvbF9uYW1lcyA9IGMoInVrX2dyaWRfY29kZSIsICJ4IiwgInkiLCAibm8yIikpCgojIENyZWF0ZSBlbXB0eSBkYXRhIGZyYW1lCm5vMl9hbGwgPC0gZGF0YV9mcmFtZSgpCgojIEZvciBlYWNoIHllYXIsIGJpbmQgcm93cyB0byBvbmUgZGF0YXNldApmb3IgKGkgaW4gMjAxMDoyMDE5KSB7CiAgZGZfbmFtZSA8LSBwYXN0ZTAoIm5vMl8iLCBpKQogIGRmX2lucHV0IDwtIGFzLm5hbWUoZGZfbmFtZSkKICAKICBkZiA8LSBldmFsKGRmX2lucHV0KSAlPiUgCiAgICBtdXRhdGUoeWVhciA9IGkpCiAgCm5vMl9hbGwgPC0gYmluZF9yb3dzKG5vMl9hbGwsIGRmKQogIH0KYGBgCgpgYGB7cn0KIyBSZW1vdmUgbWlzc2luZyBOTzIgZ3JpZCB2YWx1ZXMKbm8yX2NsZWFuIDwtIG5vMl9hbGwgJT4lIAogIGZpbHRlcihubzIgIT0gIk1JU1NJTkciKQpgYGAKCmBgYHtyfQpsaWJyYXJ5KHByb2o0KQpwcm9qNHN0cmluZyA8LSAiK3Byb2o9dG1lcmMgK2xhdF8wPTQ5ICtsb25fMD0tMiAraz0wLjk5OTYwMTI3MTcgK3hfMD00MDAwMDAgK3lfMD0tMTAwMDAwICtlbGxwcz1haXJ5ICtkYXR1bT1PU0dCMzYgK3VuaXRzPW0gK25vX2RlZnMiCgpubzJfY2xlYW5fcm93IDwtIG5vMl9jbGVhbiAlPiUgCiAgcm93aWRfdG9fY29sdW1uKCkKCiMgU291cmNlIGRhdGEKeHkgPC0gbm8yX2NsZWFuX3JvdyAlPiUgCiAgc2VsZWN0KHgsIHksIHJvd2lkKQoKIyBUcmFuc2Zvcm1lZCBkYXRhCnBqIDwtIHByb2plY3QoeHksIHByb2o0c3RyaW5nLCBpbnZlcnNlPVRSVUUpCmxhdGxvbiA8LSBkYXRhLmZyYW1lKHh5LCBsYXQ9cGokeSwgbG9uPXBqJHgpCmZpbmFsIDwtICBtZXJnZShubzJfY2xlYW5fcm93LCBsYXRsb24sIGJ5LnggPSAicm93aWQiLCBieS55ID0gInJvd2lkIikgJT4lCiAgZmlsdGVyKHllYXIgPT0gMjAxOSkgJT4lIAogIHNlbGVjdChsYXQsIGxvbiwgbm8yKSAKYGBgCgpgYGB7cn0KZmluYWwgPC0gZmluYWwgJT4lIAogIG11dGF0ZShubzIgPSBhcy5udW1lcmljKG5vMikpIApgYGAKCmBgYHtyfQpiaW5zIDwtIGMoMSwgMiwgMywgNCwgNSwgNiwgNywgOCwgOSwgMTApCnBhbCA8LSBjb2xvckJpbigiU3BlY3RyYWwiLCBkb21haW4gPSBmaW5hbCRubzIsIGJpbnMgPSBiaW5zLCBuYS5jb2xvciA9ICJ0cmFuc3BhcmVudCIsIHJldmVyc2UgPSBUUlVFKQoKbGVhZmxldCgpICU+JQogIGFkZFByb3ZpZGVyVGlsZXMoIkNhcnRvREIuUG9zaXRyb24iLCBvcHRpb25zID0gcHJvdmlkZXJUaWxlT3B0aW9ucyhub1dyYXAgPSBUUlVFKSkgJT4lCiAgc2V0VmlldyhsbmcgPSAtNC4yMDI2LCBsYXQgPSA1NS44LCB6b29tID0gNC43LCBvcHRpb25zID0gbGlzdCgpKSAlPiUKICBhZGRIZWF0bWFwKGRhdGEgPSBmaW5hbCwKICAgICAgICAgICAgIGxuZyA9IH5sb24sCiAgICAgICAgICAgICBsYXQgPSB+bGF0LAogICAgICAgICAgICAgaW50ZW5zaXR5ID0gfm5vMiwKICAgICAgICAgICAgIG1pbk9wYWNpdHkgPSAwLjEsCiAgICAgICAgICAgICBtYXggPSA0MCwKICAgICAgICAgICAgIHJhZGl1cyA9IDEsCiAgICAgICAgICAgICBibHVyID0gMSkgJT4lIAogIGFkZExlZ2VuZChwYWwgPSBwYWwsIHZhbHVlcyA9IGZpbmFsJG5vMiwKICAgICAgICAgICAgICAgIHRpdGxlPSJBdmVyYWdlIE5PMiBDb25jIikKYGBgCgpgYGB7cn0KZmluYWwgJT4lIAogIGhlYWQoKQpgYGAKCmBgYHtyfQp3cml0ZV9jc3YoZmluYWwsICJubzJfbGF0X2xvbmdfZGF0YS5jc3YiKQpgYGAKCmBgYHtyfQpubzJfYW5udWFsX21lYW4gPC0gcmVhZF9vZHMoaGVyZSgicmF3X2RhdGEvTk8yX3RhYmxlcy5vZHMiKSwgc2hlZXQgPSAzLCBza2lwID0gMikgJT4lIAogIGNsZWFuX25hbWVzKCkKYGBgCgpgYGB7cn0Kbm8yX2FubnVhbF9tZWFuX2FsbCA8LSBubzJfYW5udWFsX21lYW4gJT4lIAogIGZpbHRlcihzaXRlID09ICJBbGwgc2l0ZXMiKSAlPiUgCiAgbXV0YXRlKHllYXIgPSBhcy5udW1lcmljKHllYXIpKQpgYGAKCmBgYHtyfQpubzJfYW5udWFsX21lYW5fYWxsICU+JSAKICBnZ3Bsb3QoKSArCiAgYWVzKHggPSB5ZWFyLCB5ID0gYW5udWFsX21lYW5fbm8yY29uY2VudHJhdGlvbl9tZ19tMykgKyAKICBnZW9tX3BvaW50KCkgKwogIGdlb21fc21vb3RoKHNlID0gRkFMU0UpICsKICB0aGVtZV9taW5pbWFsKCkgKwogIHNjYWxlX3lfY29udGludW91cyhicmVha3MgPSBzZXEoMCwgNzAsIDEwKSwgbGltaXRzID0gYygwLCA3MCkpICsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCB2anVzdCA9IDAuNSwgaGp1c3Q9MSkpICsKICBsYWJzKHggPSAiXG5ZZWFyXG4iLCAKICAgICAgIHkgPSAiXG5Bbm51YWwgTWVhbiBOTzIgQ29uYyBtZyBtM1xuIiwKICAgICAgIHRpdGxlID0gIlxuTk8yIG92ZXIgdGltZSBpbiB0aGUgVUtcbiIpIApgYGAKCgpgYGB7cn0KbGlicmFyeSh0aWR5dmVyc2UpCmxpYnJhcnkoZmFibGUpCmxpYnJhcnkodHNpYmJsZSkKbGlicmFyeSh0c2liYmxlZGF0YSkKbGlicmFyeShnZ2ZvcnRpZnkpCmBgYAoKYGBge3J9CmZvcmVjYXN0X25vMiA8LSBubzJfYW5udWFsX21lYW5fYWxsICU+JSAKICBkcGx5cjo6c2VsZWN0KHllYXIsIGFubnVhbF9tZWFuX25vMmNvbmNlbnRyYXRpb25fbWdfbTMpICU+JSAKICB0c2liYmxlKGluZGV4ID0geWVhcikKYGBgCgpgYGB7cn0KYXV0b3Bsb3QoZm9yZWNhc3Rfbm8yKQpgYGAKCmBgYHtyfQpmaXQgPC0gZm9yZWNhc3Rfbm8yICU+JQogIG1vZGVsKAogICAgbWVhbl9tb2RlbCA9IE1FQU4oYW5udWFsX21lYW5fbm8yY29uY2VudHJhdGlvbl9tZ19tMyksCiAgICBhcmltYSA9IEFSSU1BKGFubnVhbF9tZWFuX25vMmNvbmNlbnRyYXRpb25fbWdfbTMpCiAgKQpmaXQKYGBgCgpgYGB7cn0KZm9yZWNhc3RfMSA8LSBmaXQgJT4lCiAgZmFibGV0b29sczo6Zm9yZWNhc3QoaCA9IDE1KQpmb3JlY2FzdF8xCmBgYAoKYGBge3J9CmZvcmVjYXN0XzEgJT4lCiAgYXV0b3Bsb3QoZm9yZWNhc3Rfbm8yKSArCiAgZ2d0aXRsZSgiRm9yZWNhc3RzIGZvciBBdXN0cmFsaWFuIGJlZXIgc2FsZXMiKSArCiAgeGxhYigiWWVhciIpICsKICBndWlkZXMoY29sb3VyID0gZ3VpZGVfbGVnZW5kKHRpdGxlID0gIkZvcmVjYXN0IikpCmBgYAoK